EC2 Auto Scalingのヘルスチェックの落とし穴(デフォルトはEC2ステータスチェックのみだよ!)
こんにちは!AWS事業本部のおつまみです。
皆さんお馴染みのWEBシステム構成「ALB+EC2+RDS」に冗長性を持たせるために「EC2 AutoScaling」を設定した際に盛大にハマったので、備忘録として残しておきます。
これだけは今日覚えて帰って欲しい
AutoScalingのヘルスチェックタイプはデフォルトだとEC2ステータスチェックのみだよ!
必要に応じて、ELBのヘルスチェックタイプも適切に設定しようね!
(私のことは忘れても、これだけは今日覚えて帰ってください。)
構築したAWS構成
今回このような構成を作成し、EC2の起動・停止に合わせて、EC2 AutoScalingがどのようにスケーリングするか確認しようとしました。
こちらの構成はCloudFormationで構築しました。 (今回の記事に関係するAutoScaling Groupの部分のみ一部抜粋しています)
# ------------------------------------------------------------# # AutoScaling Group # ------------------------------------------------------------# AutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: AutoScalingGroupName: !Sub "${PJPrefix}-autoscalinggroup" # Virtual Private Cloud (VPC) のサブネット ID のリスト # 起動させるサブネットを指定 VPCZoneIdentifier: - !Ref Private1Subnet - !Ref Private2Subnet # 起動テンプレート LaunchTemplate: # 起動テンプレートのID LaunchTemplateId: !Ref 'EC2InstanceLaunchTemplate' # 起動テンプレートのバージョン番号 Version: !GetAtt 'EC2InstanceLaunchTemplate.LatestVersionNumber' # ALBの場合紐づけるTargetGroupを指定する TargetGroupARNs: - !Ref TargetGroup # 台数設定 DesiredCapacity: 2 MaxSize: 4 MinSize: 2 Tags: - Key: Name Value: !Sub "${PJPrefix}-server" PropagateAtLaunch: true
あれ?スケーリングしないぞ..?
今回EC2にはユーザデータでApacheをインストールしたのですが、ELBのヘルスチェックにはunhealthyが返ってきてしまいました。
注意 今回の記事内容から逸れますが、ApachインストールのみではALBのヘルスチェックに失敗します。
理由:デフォルトだとドキュメントルート配下にテストファイルがないため。
対処:ヘルスチェックを成功にするためにも、ドキュメントルート配下に配下にindex.htmlを置きましょう。(Apacheの場合、/var/www/htmlです)
話は戻りますが、本来であれば、ELBがUnhealthyになっているのでEC2がスケールアウトしそうです。ですが、インスタンス2台のまま一向に増える気配がありません。。
なぜスケーリングしなかったのか?
はい、皆さんお気づきでしょうか。。
HealthCheckTypeの指定を忘れていました。
# ------------------------------------------------------------# # AutoScaling Group # ------------------------------------------------------------# AutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: AutoScalingGroupName: !Sub "${PJPrefix}-autoscalinggroup" # Virtual Private Cloud (VPC) のサブネット ID のリスト # 起動させるサブネットを指定 VPCZoneIdentifier: - !Ref Private1Subnet - !Ref Private2Subnet # 起動テンプレート LaunchTemplate: # 起動テンプレートのID LaunchTemplateId: !Ref 'EC2InstanceLaunchTemplate' # 起動テンプレートのバージョン番号 Version: !GetAtt 'EC2InstanceLaunchTemplate.LatestVersionNumber' # ALBの場合紐づけるTargetGroupを指定する TargetGroupARNs: - !Ref TargetGroup # 台数設定 DesiredCapacity: 2 MaxSize: 4 MinSize: 2 Tags: - Key: Name Value: !Sub "${PJPrefix}-server" PropagateAtLaunch: true
EC2 AutoScalingのヘルスチェックについて調べてみた
EC2 AutoScalingはAutoScalingグループ内のEC2が全て正常な状態で起動されるように、インスタンスが正常か異常かを判断しています。この判断をヘルスチェックと呼びます。
参考:Auto Scaling インスタンスのヘルスチェック - Amazon EC2 Auto Scaling (日本語)
ヘルスチェックには全部で3つのパターンがあります。
- Amazon EC2ステータスチェック (※デフォルトで有効)
- Elastic Load Balancing(ELB)
- カスタムヘルスチェック
※ちなみに、ヘルスチェックにより異常と判断されたEC2インスタンスをAutoScalingGroupから切り離し、正常なインスタンスをサービスインさせることをAuto Healingと呼びます。
・Amazon EC2ステータスチェック
・インスタンスの状態がrunnning以外の場合、もしくはステータスimpairedの場合に異常とみなされます。デフォルトで有効になっていて無効化が出来ません。
・単純にEC2インスタンス自体の状態確認をチェックすることができます。
・Elastic Load Balancing(ELB)
・ELBのターゲットグループのヘルスチェックでunhealthyとなったインスタンスを異常とみなします。デフォルトは無効になっています。
・Auto ScalingグループとELBが関連付けられている場合にオプションで選択可能です。
・OSレベルの状態確認だけではなく、EC2インスタンスのサービスが停止しているといったアプリケーションレベルでのチェックができます。
・カスタムヘルスチェック
・ユーザーが独自で用意した監視をヘルスチェックとして使用し、unhealthyとなったインスタンスを異常とみなします。こちらもデフォルトでは無効になっています。
つまり、デフォルトではEC2ステータスチェックしかありません。(覚えて帰って欲しいので何回もいいます) そのため今回はELBのヘルスチェックに失敗していても、EC2がステータスチェックOKだったため、AutoScalingはインスタンスを異常と判断しませんでした!
対応方法
ASGのセクションにHealthCheckTypeを指定して、環境を作り直します。
# ------------------------------------------------------------# # AutoScaling Group # ------------------------------------------------------------# AutoScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: AutoScalingGroupName: !Sub "${PJPrefix}-autoscalinggroup" # Virtual Private Cloud (VPC) のサブネット ID のリスト # 起動させるサブネットを指定 VPCZoneIdentifier: - !Ref Private1Subnet - !Ref Private2Subnet # 起動テンプレート LaunchTemplate: # 起動テンプレートのID LaunchTemplateId: !Ref 'EC2InstanceLaunchTemplate' # 起動テンプレートのバージョン番号 Version: !GetAtt 'EC2InstanceLaunchTemplate.LatestVersionNumber' # ヘルスチェックタイプ HealthCheckType: ELB # ALBの場合紐づけるTargetGroupを指定する TargetGroupARNs: - !Ref TargetGroup # 台数設定 DesiredCapacity: 2 MaxSize: 4 MinSize: 2 Tags: - Key: Name Value: !Sub "${PJPrefix}-server" PropagateAtLaunch: true
無事、ELBのヘルスチェックが有効になりぼこぼこEC2が起動するようになりました!
しばらく見守っていたところ、インスタンスの起動→ヘルスチェック失敗を検知→インスタンスを終了→新しいインスタンスを起動→・・の負のループ
に陥っていたので、そっとスタックを削除しました。
最後に
Cloud Formationでの環境構築は大変便利ですが、必須ではないパラメータの指定が漏れがちになるなぁと改めて学びました。 これからはパラメータを1つ1つ確認してから設定していこうと思います。
最後までお読みいただきありがとうございました!
以上、おつまみ(@AWS11077)でした!